package com.study.chapter07;

import com.study.entity.Event;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.KeyedProcessFunction;
import org.apache.flink.streaming.api.functions.source.SourceFunction;
import org.apache.flink.util.Collector;

/**
 * @Description:
 * @Author: LiuQun
 * @Date: 2022/8/5 21:08
 */
public class KeyedProcessFuncTest2 {
    public static void main(String[] args) throws Exception {
        //环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);


        env.addSource(new CustomSource())
                //分配水位线
                .assignTimestampsAndWatermarks(
                        WatermarkStrategy.<Event>forMonotonousTimestamps()
                        .withTimestampAssigner((data,l) -> data.timestamp)
                )
                .keyBy(data -> true)
                //处理函数
                .process(new KeyedProcessFunction<Boolean, Event, String>() {

                    @Override
                    public void processElement(Event value, Context ctx, Collector<String> out) throws Exception {
                        out.collect("数据到达，时间戳："+ ctx.timestamp());
                        out.collect("数据到达，水位线：" + ctx.timerService().currentWatermark());
                        //注册一个事件定时器
                        ctx.timerService().registerEventTimeTimer(ctx.timestamp() + 10 * 1000L);

                    }

                    @Override
                    public void onTimer(long timestamp, OnTimerContext ctx, Collector<String> out) throws Exception {
                        out.collect("定时触发，触发时间：" + timestamp);
                    }
                })
                .print();

        env.execute();
    }

    public static class CustomSource implements SourceFunction<Event>{

        @Override
        public void run(SourceContext<Event> ctx) throws Exception {
            // 直接发出测试数据
            ctx.collect(new Event("Mary", "./home", 1000L));
            // 为了更加明显，中间停顿5秒钟
            Thread.sleep(5000L);

            // 发出10秒后的数据
            ctx.collect(new Event("Mary", "./home", 11000L));
            Thread.sleep(5000L);

            // 发出10秒+1ms后的数据
            ctx.collect(new Event("Alice", "./cart", 11001L));
            Thread.sleep(5000L);
        }

        @Override
        public void cancel() {

        }
    }
}
